package com.zh.work.service.platform.channel.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.zh.common.entity.JSONResult;
import com.zh.work.entity.JunyuLogEntity;
import com.zh.work.entity.StatisticalEntity;
import com.zh.work.service.platform.channel.JunyuLogService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * code is far away from bug with the animal protecting
 * ┏┓　　　┏┓
 * ┏┛┻━━━┛┻┓
 * ┃　　　　　　　┃
 * ┃　　　━　　　┃
 * ┃　┳┛　┗┳　┃
 * ┃　　　　　　　┃
 * ┃　　　┻　　　┃
 * ┃　　　　　　　┃
 * ┗━┓　　　┏━┛
 * 　　┃　　　┃神兽保佑
 * 　　┃　　　┃代码无BUG！
 * 　　┃　　　┗━━━┓
 * 　　┃　　　　　　　┣┓
 * 　　┃　　　　　　　┏┛
 * 　　┗┓┓┏━┳┓┏┛
 * 　　　┃┫┫　┃┫┫
 * 　　　┗┻┛　┗┻┛
 *
 * @version 1.0
 * @Description : 骏聿日志业务实现
 * @Author : chenfei
 * @Create in : 2020/10/21 16:11
 */
@Service
public class JunyuLogServiceImpl implements  JunyuLogService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public JSONResult<List<JunyuLogEntity>> selectJunyuLogPage(Page<JunyuLogEntity> page, String addStartTime, String addEndTime, JunyuLogEntity param) {
        JSONResult<List<JunyuLogEntity>> jsonResult = new  JSONResult<>();
        //总数
        Aggregation aggCount = paramAggregationPage( page,  addStartTime,  addEndTime,  param,1);
        AggregationResults<JunyuLogEntity> resultscount = mongoTemplate.aggregate(aggCount, "jy_api", JunyuLogEntity.class);
        //分页
        Aggregation agg = paramAggregationPage(page, addStartTime, addEndTime,  param,2);
        AggregationResults<JunyuLogEntity> results = mongoTemplate.aggregate(agg, "jy_api", JunyuLogEntity.class);
        jsonResult.setTotal(Long.valueOf(resultscount.getMappedResults().get(0).getMethod()));
        jsonResult.setData(results.getMappedResults());
        return  jsonResult;
    }

    @Override
    public List<JunyuLogEntity> selectJunyuLogDownLoad(String addStartTime, String addEndTime, JunyuLogEntity param) {
        Aggregation agg = paramAggregationDownLoad(addStartTime,  addEndTime,  param);
        AggregationResults<JunyuLogEntity> results = mongoTemplate.aggregate(agg, "jy_api", JunyuLogEntity.class);
        return  results.getMappedResults();
    }

    @Override
    public List<StatisticalEntity> selectStatisticsJunyuLogPage() {
        Date startDate = DateUtil.beginOfYear(new Date());
        Date endDate =DateUtil.endOfYear(new Date());
        List<DateTime> dateTimes = DateUtil.rangeToList(startDate,endDate, DateField.MONTH);//获取今年的月份
        List<StatisticalEntity> data = new ArrayList<>();
        for(int i=0 ; i<dateTimes.size();i++){
            String startTime =null;
            String endTime = null;
            if(i>10){//统计最后一个月
                startTime = dateTimes.get(i).toString();
                endTime =  DateUtil.endOfYear(new Date()).toString();
            }else{
                startTime = dateTimes.get(i).toString();
                endTime = dateTimes.get(i+1).toString();
            }
            Criteria criteria = Criteria.where("timestamp").gte(startTime).lt(endTime);
            Aggregation agg = Aggregation.newAggregation(
                    Aggregation.match(criteria),
                    Aggregation.match(Criteria.where("flag").is("0")),
                    Aggregation.count().as("method")
            );
            Aggregation failAgg = Aggregation.newAggregation(
                    Aggregation.match(criteria),
                    Aggregation.match(Criteria.where("flag").ne("0")),
                    Aggregation.count().as("method")
            );
            AggregationResults<JunyuLogEntity> results = mongoTemplate.aggregate(agg,"jy_api",JunyuLogEntity.class);
            AggregationResults<JunyuLogEntity> failResult = mongoTemplate.aggregate(failAgg,"jy_api",JunyuLogEntity.class);
            int suNum = Objects.equals(results.getMappedResults().size(),0) ? 0 :Integer.valueOf(results.getMappedResults().get(0).getMethod()) ;
            int failNum = Objects.equals(failResult.getMappedResults().size(),0) ? 0 :Integer.valueOf(failResult.getMappedResults().get(0).getMethod()) ;
            if(!Objects.equals(0,suNum)){
                StatisticalEntity statisticalEntity = new StatisticalEntity();
                statisticalEntity.setLabel(startTime.substring(0,7));
                statisticalEntity.setType("成功");
                statisticalEntity.setValue(suNum);
                data.add(statisticalEntity);
            }
            if(!Objects.equals(0,failNum)){
                StatisticalEntity statisticalEntityFail = new StatisticalEntity();
                statisticalEntityFail.setLabel(startTime.substring(0,7));
                statisticalEntityFail.setType("失败");
                statisticalEntityFail.setValue(failNum);
                data.add(statisticalEntityFail);
            }
        }
        return  data;
    }

    /**
     * 生成聚合函数
     * @param addStartTime
     * @param addEndTime
     * @param param
     * @return
     */
    private Aggregation paramAggregationDownLoad (String addStartTime, String addEndTime, JunyuLogEntity param){
        Criteria criteria1 = new Criteria();
        Criteria criteria2 = new Criteria();
        Criteria criteria3 = new Criteria();
        Criteria criteria4 = new Criteria();
        Criteria criteria5 = new Criteria();
        if(Objects.nonNull(param.getSname())){
            criteria1 = Criteria.where("sName").is(param.getSname());
        }
        if(Objects.nonNull(param.getMethod())){
            criteria2  =Criteria.where("method").is(param.getMethod()) ;
        }
        if(Objects.nonNull(addStartTime) && Objects.nonNull(addEndTime)){
            criteria3 = Criteria.where("timestamp").gte(addStartTime).lt(addEndTime);
        }
        if(Objects.nonNull(param.getSid())){
            criteria4 = Criteria.where("sId").is(param.getSid());
        }
        if(Objects.nonNull(param.getResult())){
            criteria5 = Criteria.where("result").regex(param.getResult());
        }
        Aggregation agg = Aggregation.newAggregation(
                Aggregation.match(criteria1),
                Aggregation.match(criteria2),
                Aggregation.match(criteria3),
                Aggregation.match(criteria4),
                Aggregation.match(criteria5),
                Aggregation.sort(Sort.Direction.DESC, "timestamp"),
                Aggregation.group("_id").first("result").as("result").first("sType").as("stype").
                        first("uId").as("uid").first("timed").as("timed").first("flag").as("flag").
                        first("method").as("method").first("sName").as("sname").first("sPhoto").as("sphoto").
                        first("sId").as("sid").first("timestamp").as("timestamp").
                        first("sMobile").as("smobile").first("sBankCard").as("sbankCard")
        );
        return agg;
    }

    /**
     * 生成聚合函数
     * @param page
     * @param addStartTime
     * @param addEndTime
     * @param param
     * @param type 为1 则是查询总数的聚合函数，否则为查询分页的聚合函数
     * @return
     */
    private Aggregation paramAggregationPage (Page<JunyuLogEntity> page,  String addStartTime, String addEndTime, JunyuLogEntity param ,int type){
        Criteria criteria1 = new Criteria();
        Criteria criteria2 = new Criteria();
        Criteria criteria3 = new Criteria();
        Criteria criteria4 = new Criteria();
        Criteria criteria5 = new Criteria();

        if(Objects.nonNull(param.getSname())){
            criteria1  = Criteria.where("sName").is(param.getSname()) ;
        }
        if(Objects.nonNull(param.getMethod())){
            criteria2  = Criteria.where("method").is(param.getMethod());
        }
        if(Objects.nonNull(param.getResult())){
            criteria3 = Criteria.where("result").regex(param.getResult());
        }
        if(Objects.nonNull(addStartTime) && Objects.nonNull(addEndTime)){
            criteria4 = Criteria.where("timestamp").gte(addStartTime).lt(addEndTime) ;
        }
        if(Objects.nonNull(param.getSid())){
            criteria5 = Criteria.where("sId").is(param.getSid()) ;
        }
        if(Objects.equals(type,1)){
            //总数
            Aggregation aggCount = Aggregation.newAggregation(
                    Aggregation.match(criteria1),
                    Aggregation.match(criteria2),
                    Aggregation.match(criteria3),
                    Aggregation.match(criteria4),
                    Aggregation.match(criteria5),
                    Aggregation.sort(Sort.Direction.DESC, "timestamp"),
                    Aggregation.count().as("method")
            );
            return  aggCount;
       }else{
              //分页
            Aggregation agg = Aggregation.newAggregation(
                    Aggregation.match(criteria1),
                    Aggregation.match(criteria2),
                    Aggregation.match(criteria3),
                    Aggregation.match(criteria4),
                    Aggregation.match(criteria5),
                    Aggregation.sort(Sort.Direction.DESC, "timestamp"),
                    Aggregation.skip((page.getCurrent() - 1) * page.getSize()),
                    Aggregation.limit(page.getSize()),
                    Aggregation.group("_id").first("result").as("result").first("sType").as("stype").
                            first("uId").as("uid").first("timed").as("timed").first("flag").as("flag").
                            first("method").as("method").first("sName").as("sname").first("sPhoto").as("sphoto").
                            first("sId").as("sid").first("timestamp").as("timestamp").
                            first("sMobile").as("smobile").first("sBankCard").as("sbankCard")
            );
            return  agg;
       }
    }

}
